/*
  (C) 2005 Adam D. Bradley

  This program is free software; you can redistribute it and/or
  modify it under the terms of Version 2 of the GNU General Public 
  License.
  
  This library is distributed in the hope that it will be useful,
  but WITHOUT ANY WARRANTY; without even the implied warranty of
  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
  General Public License for more details.
  
  You should have received a copy of the GNU Library General Public
  License along with this library; if not, write to the Free
  Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
*/

package step;

import java.io.*;
import java.util.ArrayList;

import snobject.snObject;
import snobject.snObjectArgList;
import snobject.snString;
import sxe.SxeClassLoader;
import step.Node;
import step.exceptions.ResourceUnavailableException;
import step.exceptions.STEPException;

public class ExpNode extends Node
{

    public ExpNode(String opcode)
    {
		super();
		Opcode = opcode;
    }

    public ExpNode(String id, String opcode)
    {
		super(id);
		Opcode = opcode;
    }
	
	protected void Bind() throws ClassNotFoundException {
		try {
			Function = SxeClassLoader.ResolveOpcode(Opcode);
		} catch(ClassNotFoundException e){
			System.err.println(e.getMessage());
			e.printStackTrace();
			throw new ClassNotFoundException("At node '" + ID + "' " + e.getMessage());
		}
		super.Bind();
	}

	/**
	 * backdoor to evaluate for alternate execution models 
	 * 
	 * @param arg
	 * @return
	 * @throws EvaluationFailure
	 */
	public snObject Evaluate(snObjectArgList arg) throws EvaluationFailure {
		
		try {
			return Function.Call(arg);
		} catch (ArrayIndexOutOfBoundsException e) {
			e.printStackTrace();
			throw new EvaluationFailure(this,e.getMessage());
		} catch (ClassCastException e) {
			e.printStackTrace();
			throw new EvaluationFailure(this,e.getMessage());
		} catch (ResourceUnavailableException e) {
			e.printStackTrace();
			throw new EvaluationFailure(this,e.getMessage());			
		}
		
		
	}
	
    public void Evaluate() throws EvaluationFailure
    {
		assert(Function != null);
		try{
			SetValue(Function.Call(this));
		}
		catch(EvaluationFailure e){
			ByteArrayOutputStream baos = new ByteArrayOutputStream();
			e.printStackTrace(new PrintStream(baos));
			String s = baos.toString();//.replaceAll("\n", "<BR>");
			value = new snString("FAILURE:" + "\n" + s );
			throw e;
		}
		//System.out.println("Evaluated: "+ this.ID +"," + this.Opcode + ".  Result=" + super.value.toString());
		rt_evaluated = true;
		PushResult();
		
		// clear that our children are fresh
		ClearFreshInputs();
		
    }
	
    protected String Opcode;
    protected FunctionWrapper Function;

    public String getOpcode(){ return Opcode; }

    // Serializer
    public String TagName() { return "exp"; }
    public void Write(OutputStream out, int depth) throws java.io.IOException {
	WriteBasis(out, depth, "opcode=\"" + Opcode + "\"");
    }
    
    public String toString(){
    	return "<html><center>\"" + super.ID + "\"<br>" + Opcode + "</center><html>"; 
    }
    
	/* returns a line for a DOT file to represent this node 
	 * may be overwritten by particular nodes to augment output
	 */
	public String GetDOTLine(){
		return "\"" + this.Opcode + "\\n" + this.ID + "\"";
	}

	// this code is added by ray
	//	 MODIFIES: compilationErrors 
	// EFFECT: checks if an Expression node doesn't have matchimg children to its specification it adds exceptions to compilationErrors 
	public void validate(step.Graph g,
			ArrayList<STEPException> compilationErrors) {
			// this method is not implemented it is part of the future work
	}
	
	@Override
    public String serializeAsSnafu(){
    	StringBuffer sb = new StringBuffer(this.Opcode.substring((this.Opcode.lastIndexOf(".")+1)));

    	if(!IsLeaf()){
    		sb.append("(");
    		sb.append(children[0].serializeAsSnafu());
    		for(int i=1;i<children.length;i++){
        		sb.append(",");
        		sb.append(children[i].serializeAsSnafu());
    		}
    		sb.append(")");
    	}
    	return sb.toString();
    }
	
	@Override
	public Node ShallowCopy() {
		ExpNode  cn = new ExpNode(ID, Opcode);
		Node.CopyNonRTPropertiesFromAtoB(this,cn);
		return cn;
	}
}
